﻿using System;
using System.Collections.Generic;
using System.IO;
using SDT.CacheSystem;
using SDT.CrawlSystem.Servers.Filters;
using SDT.LogSystem;
using SDT.ServiceSystem;
using SDT.Libraries.Utilities;
using SDT.DataService.Services;

namespace SDT.CrawlSystem.Servers
{
    /// <summary>
    /// Written by TungNX
    /// </summary>
    public sealed class UrlWorkUnit : WorkUnit
    {
        #region Logging
        private static LogHelper Logger = new LogHelper(
          string.Format("{0}url.cache.log", Global.Instance.LogFile.Substring(0, Global.Instance.LogFile.LastIndexOf(Path.DirectorySeparatorChar) + 1)));

        internal static void FlushLog()
        {
            lock (Logger)
                Logger.Flush();
        }
        #endregion

        private static readonly IRAMCache<string, string> TheCache = new RAMCache<string, string>(10000);
        private PageService svPage = new PageService();

        #region Filters
        private IUrlFilter uFilter = null;
        public IUrlFilter UFilter
        {
            get { return uFilter; }
        }

        private IWIDFilter iFilter = null;
        public IWIDFilter IFilter
        {
            get { return iFilter; }
        }
        //Chọn vùng web để lấy HTML. Để không bị lẫn html với vùng khác
        //Author: TungNX
        //Created Date : 23/12/2010
        private Filter rFilter = null;
        public Filter RFilter
        {
            get { return rFilter; }        
        }

        #endregion

        #region Results
        private string rawHtml = "";
        public string RawHtml
        {
            get { lock(this) return Ready ? rawHtml : null; }
            internal set { lock(this) rawHtml = value; }
        }

        private IList<string> wids = null;
        public IList<string> WIDs
        {
            get
            {
                if (wids != null)
                    return wids;

                if (Ready && Links != null && Links.Count > 0)
                {
                    wids = new List<string>(Links.Count);
                    foreach (var i in Links)
                        wids.Add(iFilter.GetWID(i.Href));
                }
                return wids;
            }
        }
      /// <summary>
      /// TungNX
      /// Modified Date: 24/2/2011
      /// Vùng dữ liệu rawHTML được tách ra thành vùng nhỏ hơn
      /// </summary>
        private IList<ImgDes> links = null;
        public IList<ImgDes> Links
        {
            get
            {
                if (links != null)
                    return links;

                #region Sửa vùng RawHTML Modified Date: 24/2/2011
                //if (Ready)
                 // links = UrlParser.ParserUrls(RawHtml, UFilter,"");      
                string txt = null;
                //truong hop không định nghĩa phần từ HTML Filter, hệ thống không bị lỗi
                if (rFilter != null)
                {
                    if (this.RFilter.DataSource == Filter.Regions.CONTENT) // truong hop region là content thì mới bóc tách ra vùng cần lấy
                        RawHtml = this.RFilter.DoFilter(RawHtml, txt, ref txt, true);
                }
                #endregion
                if (Ready)
                    links = UrlParser.ParserUrls(RawHtml, UFilter, UrlPrefix); // Ngày 20/09/2111 Lê Việt Sửa đối số truyền vào của hàm UrlParser.ParserUrls(RawHtml, UFilter,"") => (RawHtml, UFilter, UrlPrefix)      
            
                //if (Ready)
                //    links = UrlParser.FindUrls(RawHtml, UFilter, "");

                return links;
            }
        }

        public override void ClearResult()
        {
            lock (this)
            {
                RawHtml = "";
                if (wids != null) wids.Clear();
                wids = null;

                if (links != null) links.Clear();
                links = null;
            }
        }

        private string StandardizeUrl(string url)
        {
            var u = url;

            #region Remove url's prefix
            if (u.StartsWith(UrlPrefix))
                u = u.Substring(UrlPrefix.Length);
            #endregion

            #region Add back slash
            if (!u.StartsWith("/"))
                u = string.Format("/{0}", u);
            #endregion

            return u;
        }

        public void SaveResult()
        {
            if (!Ready)
                return;

            lock (this)
            {
                nurls = 0;

                if (Links != null && WIDs != null && Links.Count > 0)
                for (int i = 0; i < Links.Count; i++)
                {
                    var v = WIDs[i];
                    if (v == string.Empty)
                        continue;

                    var k = StandardizeUrl(Links[i].Href);
                    var img1 = Links[i].UrlImage;
                    img1 = img1.ToString().Trim();
                    var img = img1 != null && img1.Length > 0 ? img1 : null;
                    #region Already existed in CACHE
                    if (TheCache.CacheHit(k) != null) { 
                        //lock (Logger)
                          // Logger.AddEntry(String.Format("HIT:   {0} {1}", v, k)); 
                    }
                        //lock (Logger)
                           // Logger.AddEntry(String.Format("HIT:   {0} {1}", v, k));
                    #endregion
                    else
                    {
                        #region Add to CACHE
                        TheCache.Add(k, v);
                        lock (Logger)
                            Logger.AddEntry(String.Format("MISS:  {0}", v));
                        #endregion

                        #region Insert data into database
                        try
                        {
                            // Xét trường hợp lấy cho chothai.vn link có chứa mã ngẫu nhiên dạng:"/showthread.php?goto=newpost&amp;t=234548" => "/showthread.php?t=234548"
                            var ts = "goto=newpost&amp;";
                            // Xét trường hợp ICon của chợ thái mặc định có "defaultbeta/statusicon","smilies/yahoo"
                            if(this.channelId ==1 && k.Contains(ts) ) k = k.Remove(k.IndexOf(ts),ts.Length);

                            if (!string.IsNullOrEmpty(img) && (img.Contains("yahoo") || img.Contains("defaultbeta/statusicon") || img.Contains("avatars/noavatar") || img.Contains("item/item-no-img") || img.Contains("firstnew.gif") || img.Contains("no-pic.gif") || img.Contains("http://hanoicity.jaovat.com/") || img.Contains("customer.gif"))) img = null;
                            var uid = svPage.InsertPage(this.channelId, this.pageId, k,img, string.Format("{0}{1}",this.UrlPrefix,k), v);  
                            
                            if (uid > 0)
                            {
                                nurls++;
                                totalUrls++;
                            }
                        }
                        catch(Exception ex) { }
                        #endregion
                    }
                }

                lock (Logger)
                    Logger.AddEntry(String.Format("\r\nTOTAL={0} INS={1} @{2}-{3}-{4}\r\n", totalUrls, nurls, channelId, pageId, pageNo));

                ClearResult();
            }
        }
        #endregion

        #region Data members
        private int channelId = 0;
        public int ChannelId
        {
            get { return channelId; }
        }

        private int pageId = 0;
        public int PageId
        {
            get { return pageId; }
        }

        private string url = "";
        public string Url
        {
            get { return url; }
        }

        private string urlPrefix = "";
        public string UrlPrefix
        {
            get { return urlPrefix; }
        }

        private int pageNo = 0;
        public int PageNo
        {
            get { return pageNo; }
        }

        private int totalUrls = 0;
        public int TotalUrls
        {
            get { return totalUrls; }
        }

        private int nurls = 0;
        public int nUrls
        {
            get { return nurls; }
        }
        #endregion

        #region Constructors
               /// <summary>
        /// Author: TungNX
        /// Created Date: 24/2/2011
        /// Thêm tham số khởi tạo Filter để lọc ra vùng cần lấy url
        /// </summary>
        /// <param name="channelId"></param>
        /// <param name="pageId"></param>
        /// <param name="uFilter"></param>
        /// <param name="iFilter"></param>
        /// <param name="rFilter"></param>
        /// <param name="urlPrefix"></param>
        /// <param name="url"></param>
        /// <param name="pageNo"></param>
        public UrlWorkUnit(int channelId, int pageId, IUrlFilter uFilter, IWIDFilter iFilter,Filter rFilter, string urlPrefix, string url, int pageNo)
            : base()
        {
            this.channelId = channelId;
            this.pageId = pageId;
            this.url = url;
            this.uFilter = uFilter;
            this.iFilter = iFilter;
            this.urlPrefix = urlPrefix;
            this.rFilter = rFilter;
            this.pageNo = pageNo;
        }
        #endregion  
    }
}